package com.rp.data.tcp_ws.server_tcp.echo;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class DecoderHandler extends ByteToMessageDecoder {

    private static final Logger log = LogManager.getLogger(DecoderHandler.class);


    private static final ConcurrentHashMap<String, ChannelHandlerContext> ctxMap = new ConcurrentHashMap<>();

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    public String remoteIp(String ip) {
        try {
            return ip.replace("/", "").substring(0, ip.indexOf(":") - 1);
        } catch (Exception e) {
            return ip;
        }
    }

    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> list) {
        String ip = remoteIp(ctx.channel().remoteAddress().toString());
        if (ctxMap.containsKey(ip)) {
            ChannelHandlerContext ctx2 = ctxMap.get(ip);
            if (!ctx2.channel().equals(ctx.channel())) {
                log.info("ctx1：" + ctx.channel().remoteAddress());
                log.info("ctx2：" + ctx2.channel().remoteAddress());
                ctxMap.remove(ip);
                ctx2.close();
                ctxMap.put(ip, ctx);
            }
        } else {
            ctxMap.put(ip, ctx);
        }

        in.markReaderIndex();
        try {
            int start1 = 0;
            int start2 = 0;
            while (true) {
                start1 = start2;
                start2 = in.readUnsignedByte();
                if (start1 == 0x40 && start2 == 0x40) {
                    break;
                }
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutput buffer = new DataOutputStream(baos);

            //起始符号@@
            buffer.writeByte(0x40);
            buffer.writeByte(0x40);

            int end1 = 0;
            int end2 = 0;
            while (true) {
                end1 = end2;
                end2 = in.readUnsignedByte();
                buffer.writeByte(end2);
                if (end1 == 0x23 && end2 == 0x23) {
                    break;
                }
            }

            log.info("req:" + ByteUtils.bytesToHex(baos.toByteArray()));
            byte[] response = GA26875Decoder.decode(baos.toByteArray());
            log.info("rsp:" + ByteUtils.bytesToHex(response));

            ByteBuf buf = ctx.alloc().buffer(response.length);
            buf.writeBytes(response);
            ctx.writeAndFlush(buf);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.info("下线：" + ctx.channel().remoteAddress());

        String ip = remoteIp(ctx.channel().remoteAddress().toString());
        ChannelHandlerContext ctx2 = ctxMap.get(ip);
        if (ctx2.equals(ctx)) {
            ctxMap.remove(ip);
        }

        super.channelUnregistered(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error(cause.getMessage(), cause);
        ctx.close();
    }
}
